package com.app.service.impl;

import com.app.domain.bo.LinksBo;
import com.app.domain.page.Page;
import com.app.domain.po.LinksPo;
import com.app.domain.vo.LinksVo;
import com.app.framework.utils.CoBeanUtils;
import com.app.framework.utils.CollectionUtils;
import com.app.framework.utils.RedisUtils;
import com.app.mapper.LinksMapper;
import com.app.service.LinksService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 友情链接方法实现
 */
@Service
public class LinksServiceImpl extends ServiceImpl<LinksMapper, LinksPo> implements LinksService {

    /**
     * 全部友链列表
     *
     * @param bo 入参
     */
    @Override
    public Page<LinksVo> allLinks(LinksBo bo) {
        PageHelper.startPage(bo.getPageNum(), bo.getPageSize());
        List<LinksVo> linksVos = baseMapper.allLinks(bo);
        return Page.restPage(linksVos);
    }

    /**
     * 已审核友情链接列表
     *
     * @param bo 入参
     */
    @Override
    @Cacheable(cacheNames = "link", key = "#bo.getPageNum")
    public Page<LinksVo> lists(LinksBo bo) {
        PageHelper.startPage(bo.getPageNum(), bo.getPageSize());
        List<LinksVo> linksVos = baseMapper.lists(bo);
        return Page.restPage(linksVos);
    }

    /**
     * 友链申请
     *
     * @param bo 入参
     */
    @Override
    @CacheEvict(cacheNames = "all_link", allEntries = true)
    public void apply(LinksBo bo) {
        LinksPo linksPo = CoBeanUtils.copy(bo, LinksPo.class);
        linksPo.setCreateTime(new Date());
        linksPo.setStatus(false);
        baseMapper.insert(linksPo);
    }

    /**
     * 友链审核
     *
     * @param linkId 友链ID
     */
    @Override
    @CacheEvict(cacheNames = {"all_link", "link"}, allEntries = true)
    public void examine(Long linkId) {
        LinksPo linksPo = baseMapper.selectById(linkId);
        Assert.notNull(linksPo, "该友链不存在");
        linksPo.setStatus(!linksPo.getStatus());
        baseMapper.updateById(linksPo);
    }

    /**
     * 修改友链
     *
     * @param bo 入参
     */
    @Override
    @CacheEvict(cacheNames = {"all_link", "link"}, allEntries = true)
    public void updateOne(LinksBo bo) {
        LinksPo linksPo = baseMapper.selectById(bo.getId());
        Assert.notNull(linksPo, "该友链不存在");
        CoBeanUtils.copyProperties(bo, linksPo);
        linksPo.setUpdateTime(new Date());
        baseMapper.updateById(linksPo);
    }

    /**
     * 删除友链
     *
     * @param linkId 友链ID
     */
    @Override
    @CacheEvict(cacheNames = {"all_link", "link"}, allEntries = true)
    public void deleteOne(Long linkId) {
        LinksPo linksPo = baseMapper.selectById(linkId);
        Assert.notNull(linksPo, "友链不存在");
        baseMapper.deleteById(linkId);
    }

    /**
     * 友链访问
     *
     * @param linkId 友链ID
     */
    @Override
    public void look(Long linkId) {
        String redisKey = "link_look_count";
        if (RedisUtils.existsHashField(redisKey, linkId)) {
            LinksPo linksPo = RedisUtils.getJsonHash(redisKey, linkId, LinksPo.class);
            linksPo.setLooks(linksPo.getLooks() + 1);
            RedisUtils.setJsonHash(redisKey, linkId, linksPo);
        } else {
            LinksPo linksPo = baseMapper.selectById(linkId);
            Assert.notNull(linksPo, "友链不存在");
            linksPo.setLooks(linksPo.getLooks() + 1);
            RedisUtils.setJsonHash(redisKey, linkId, linksPo);
        }
    }

    //--------------------------------------------------------------|↓|持久化到数据库|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|持久化到数据库|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|持久化到数据库|↓|-----------------------------------------------------------------

    /**
     * 持久化到数据库(每天凌晨1点)
     */
    @Async
    @Scheduled(cron = "0 0 1 * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void updateLinkLookCount() {
        String redisKey = "link_look_count";
        List<LinksPo> linksPos = RedisUtils.getAllJsonHash(redisKey, LinksPo.class);
        if (CollectionUtils.isEmpty(linksPos)) {
            return;
        }
        List<LinksPo> list = new ArrayList<>();
        for (LinksPo linksPo : linksPos) {
            LinksPo po = new LinksPo();
            po.setId(linksPo.getId());
            po.setLooks(linksPo.getLooks());
            list.add(po);
        }
        updateBatchById(list);
        RedisUtils.del(redisKey);
        RedisUtils.concatDeletes("link::*");
        RedisUtils.concatDeletes("all_link::*");
    }

}